package com.yc.sole.erp.biz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.yc.sole.erp.dto.CategoryDto;
import com.yc.sole.erp.dto.MoldDto;
import com.yc.sole.erp.dto.SupplierDto;
import com.yc.sole.erp.excel.MoldExcel;
import com.yc.sole.erp.exception.ErpResultEnum;
import com.yc.sole.erp.repository.CategoryRepository;
import com.yc.sole.erp.repository.MoldRepository;
import com.yc.sole.erp.repository.SupplierRepository;
import com.yc.sole.erp.request.MoldQueryReq;
import com.yc.sole.erp.request.MoldReq;
import com.yc.sole.erp.response.MoldResp;
import com.yc.sole.framework.exception.BaseException;
import com.yc.sole.framework.mybatis.page.Paging;
import com.yc.sole.framework.mybatis.util.PageUtil;
import com.yc.sole.framework.utils.EasyExcelUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 模具表 服务接口实现
 *
 * @author yizuomin
 * @date 2023-05-07
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class MoldBiz {

    private final MoldRepository moldRepository;
    private final SupplierRepository supplierRepository;
    private final CategoryRepository categoryRepository;

    /**
     * 新增
     *
     * @param moldReq
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveMold(MoldReq moldReq) {
        CategoryDto categoryDto = categoryRepository.selectCategoryById(moldReq.getCategoryId());
        if (Objects.isNull(categoryDto)) {
            throw new BaseException(ErpResultEnum.CATEGORY_NOT_FOUND);
        }
        SupplierDto supplierDto = supplierRepository.selectSupplierById(moldReq.getSupplierId());
        if (Objects.isNull(supplierDto)) {
            throw new BaseException(ErpResultEnum.SUPPLIER_NOT_FOUND);
        }
        MoldDto dto = new MoldDto();
        BeanUtil.copyProperties(moldReq, dto);
        dto.setCategoryName(categoryDto.getCategoryName());
        moldRepository.saveMold(dto);
    }

    /**
     * 修改
     *
     * @param moldReq
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateMoldById(MoldReq moldReq) {
        CategoryDto categoryDto = categoryRepository.selectCategoryById(moldReq.getCategoryId());
        if (Objects.isNull(categoryDto)) {
            throw new BaseException(ErpResultEnum.CATEGORY_NOT_FOUND);
        }
        SupplierDto supplierDto = supplierRepository.selectSupplierById(moldReq.getSupplierId());
        if (Objects.isNull(supplierDto)) {
            throw new BaseException(ErpResultEnum.SUPPLIER_NOT_FOUND);
        }
        MoldDto dto = new MoldDto();
        BeanUtil.copyProperties(moldReq, dto);
        dto.setCategoryName(categoryDto.getCategoryName());
        moldRepository.updateMoldById(dto);
    }

    /**
     * 删除
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteMoldByIds(Collection<Long> id) {
        moldRepository.deleteMoldByIds(id);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param moldPageReq
     * @return
     */
    public Paging<MoldResp> selectMoldPage(Paging<MoldQueryReq> page, MoldQueryReq moldPageReq) {
        Paging<MoldDto> paging = moldRepository.selectMoldPage(page, moldPageReq);
        Paging<MoldResp> moldRespPaging = PageUtil.pageCopy(paging, MoldResp.class);
        Set<Long> supplierIds = moldRespPaging.getRecords().stream().map(MoldResp::getSupplierId).collect(Collectors.toSet());
        List<SupplierDto> supplierDtos = supplierRepository.selectSupplierByIds(supplierIds);
        Set<Long> categoryIds = moldRespPaging.getRecords().stream().map(MoldResp::getCategoryId).collect(Collectors.toSet());
        Map<Long, CategoryDto> categoryDtoMap = categoryRepository.selectCategoryByIds(categoryIds).stream().collect(Collectors.toMap(CategoryDto::getId, v -> v));
        Map<Object, SupplierDto> supplierDtoMap = supplierDtos.stream().collect(Collectors.toMap(SupplierDto::getId, v -> v));
        for (MoldResp moldResp : moldRespPaging.getRecords()) {
            SupplierDto supplierDto = supplierDtoMap.get(moldResp.getSupplierId());
            moldResp.setSupplierName(Objects.nonNull(supplierDto) ? supplierDto.getSupplierName() : null);
            CategoryDto categoryDto = categoryDtoMap.get(moldResp.getCategoryId());
            moldResp.setCategoryName(Objects.nonNull(categoryDto) ? categoryDto.getCategoryName() : null);
        }
        return moldRespPaging;
    }

    /**
     * 通过Id查询模具
     *
     * @param moldId
     * @return
     */
    public MoldResp selectMoldById(Long moldId) {
        MoldResp moldResp = BeanUtil.copyProperties(moldRepository.selectMoldById(moldId), MoldResp.class);
        if (Objects.isNull(moldResp)) {
            return null;
        }
        SupplierDto supplierDto = supplierRepository.selectSupplierById(moldResp.getSupplierId());
        if (Objects.nonNull(supplierDto)) {
            moldResp.setSupplierName(supplierDto.getSupplierName());
        }
        return moldResp;
    }

    /**
     * 导出
     *
     * @param moldQueryReq
     */
    public void export(MoldQueryReq moldQueryReq, HttpServletResponse response) {
        List<MoldDto> moldDtos = moldRepository.selectMoldList(moldQueryReq);
        Set<Long> supplierIds = moldDtos.stream().map(MoldDto::getSupplierId).collect(Collectors.toSet());
        Set<Long> categoryIds = moldDtos.stream().map(MoldDto::getCategoryId).collect(Collectors.toSet());
        Map<Long, SupplierDto> supplierDtoMap = supplierRepository.selectSupplierByIds(supplierIds).stream().collect(Collectors.toMap(SupplierDto::getId, v -> v));
        Map<Long, CategoryDto> categoryDtoMap = categoryRepository.selectCategoryByIds(categoryIds).stream().collect(Collectors.toMap(CategoryDto::getId, v -> v));
        List<MoldExcel> moldExcelList = moldDtos.parallelStream().map(moldDto -> {
            SupplierDto supplierDto = supplierDtoMap.get(moldDto.getSupplierId());
            MoldExcel moldExcel = new MoldExcel();
            moldExcel.setMoldName(moldDto.getMoldName());
            if (Objects.nonNull(supplierDto)) {
                moldExcel.setSupplierName(supplierDto.getSupplierName());
            }
            CategoryDto categoryDto = categoryDtoMap.get(moldDto.getCategoryId());
            if (Objects.nonNull(categoryDto)) {
                moldExcel.setCategoryName(categoryDto.getCategoryName());
            }
            moldExcel.setMadeDate(moldDto.getMadeDate());
            moldExcel.setPosition(moldDto.getPosition());
            moldExcel.setRemark(moldDto.getRemark());
            return moldExcel;
        }).toList();
        EasyExcelUtil.exportExcel(response, moldExcelList, "模具信息清单");
    }

    /**
     * 导入
     *
     * @param file
     */
    public void importMold(MultipartFile file) {
        List<MoldExcel> moldExcels = EasyExcelUtil.importExcel(file, MoldExcel.class);
        Set<String> supplierNames = moldExcels.stream().map(MoldExcel::getSupplierName).collect(Collectors.toSet());
        Map<String, SupplierDto> supplierDtoMap = supplierRepository.selectSupplierByNames(supplierNames).stream().collect(Collectors.toMap(SupplierDto::getSupplierName, v -> v));

        Set<String> moleNames = moldExcels.stream().map(MoldExcel::getMoldName).collect(Collectors.toSet());
        Map<String, MoldDto> moldDtoMap = moldRepository.selectMoldListByMoldNames(moleNames).stream().collect(Collectors.toMap(MoldDto::getMoldName, v -> v));
        Set<String> categoryNames = moldExcels.stream().map(MoldExcel::getCategoryName).collect(Collectors.toSet());
        Map<String, CategoryDto> categoryDtoMap = categoryRepository.selectCategoryByNames(categoryNames).stream().collect(Collectors.toMap(CategoryDto::getCategoryName, v -> v));

        List<MoldDto> newMoldDtos = new ArrayList<>();
        for (MoldExcel moldExcel : moldExcels) {
            MoldDto moldDto = moldDtoMap.get(moldExcel.getMoldName());
            if (Objects.isNull(moldDto)) {
                moldDto = new MoldDto();
                moldDto.setMoldName(moldExcel.getMoldName());
                SupplierDto supplierDto = supplierDtoMap.get(moldExcel.getSupplierName());
                if (Objects.nonNull(supplierDto)) {
                    moldDto.setSupplierId(supplierDto.getId());
                }
                CategoryDto categoryDto = categoryDtoMap.get(moldExcel.getCategoryName());
                if (Objects.nonNull(categoryDto)) {
                    moldDto.setCategoryId(categoryDto.getId());
                }
                moldDto.setMadeDate(moldExcel.getMadeDate());
                moldDto.setPosition(moldExcel.getPosition());
                moldDto.setRemark(moldExcel.getRemark());
                newMoldDtos.add(moldDto);
            }
        }
        if (CollUtil.isNotEmpty(newMoldDtos)) {
            moldRepository.saveMold(newMoldDtos);
        }
    }

    /**
     * 模板下载
     *
     * @param response
     */
    public void downloadTemplate(HttpServletResponse response) {
        List<MoldExcel> moldExcelList = new ArrayList<>();
        MoldExcel moldExcel = new MoldExcel();
        moldExcel.setMoldName("");
        moldExcel.setSupplierName("");
        moldExcel.setMadeDate("");
        moldExcel.setPosition("");
        moldExcel.setRemark("");
        moldExcelList.add(moldExcel);
        EasyExcelUtil.exportExcel(response, moldExcelList, "模具信息模板");
    }

    /**
     * @param moldName
     * @return
     */
    public List<MoldResp> selectMoldByName(String moldName) {
        return BeanUtil.copyToList(moldRepository.selectMoldByName(moldName), MoldResp.class);
    }
}
